#ifndef __DSTH_CONNECTION_H__
#define __DSTH_CONNECTION_H__

#include <string>
#include <memory>
#include "AcfDelegate.h"
#include "ChannelBuffer.h"
#include "Timestamp.h"
#include "InetSocketAddress.h"

namespace dsth {
class EventLoop;
class Socket;
class Channel;
class Connection
{
public:
    typedef Acf::Delegate<void (Connection*, ChannelBuffer*, Timestamp)> MessageHandler;
    typedef Acf::Delegate<void (Connection*)> ConnectionHandler;

    Connection(EventLoop* loop, int id, int socket_fd,
        const InetSocketAddress& host_addr, const InetSocketAddress& peer_addr);
    ~Connection();

    void SetMessageHandler(const MessageHandler& handler) { message_handler_ = handler; }
    void SetConnectionHandler(const ConnectionHandler& handler) { conn_handler_ = handler; }
    void SetDisConnectionHandler(const ConnectionHandler& handler) { dis_conn_handler_ = handler; }
    void SetWriteCompletedHandler(const ConnectionHandler& handler) { write_completed_handler_ = handler; }
    void Send(const char* data, size_t len);
    void Send(const std::string& data);
    void Send(const ChannelBuffer& buf);
    //void SendInLoop(const char* data, size_t len);
    void ShutDown();
    int GetId() const { return id_; } 
    std::string GetPeerAdderess() const { return peer_addr_.ToHostPortFormat(); }
    std::string GetHostAdderess() const { return host_addr_.ToHostPortFormat(); }
private:
    // Can't invoke copy constructor or assignment operator
    Connection(const Connection&);
    void operator=(const Connection&);

    void OnReadEnable(Timestamp recv_time);
    void OnWriteEnable();
    void OnErrorOccur();
    void OnClose();
    void HandleSocketError();
    void ConnectEstablished();
    void ConnectDestroy();
    friend class ClientBootstrap;
    friend class ServerBootstrap;

    MessageHandler message_handler_;
    ConnectionHandler conn_handler_;
    ConnectionHandler dis_conn_handler_;
    ConnectionHandler write_completed_handler_;

    EventLoop* loop_;
    // Don't expose Socket.h&Channel.h to user
    std::auto_ptr<Socket> socket_;
    std::auto_ptr<Channel> channel_;
    ChannelBuffer inbuffer_;
    ChannelBuffer outbuffer_;
    // provide informations
    int id_;
    InetSocketAddress host_addr_;
    InetSocketAddress peer_addr_;

};

} // namespace
#endif // __DSTH_CONNECTION_H__
